//
//  NSObject+Swizzle.m
//  EPTool
//
//  Created by shiqing guo on 2018/5/9.
//  Copyright © 2018年 云数动能科技. All rights reserved.
//

#import "NSObject+Swizzle.h"
#import <objc/runtime.h>

@implementation NSObject (Subscript)
- (id)objectAtIndexedSubscript:(NSUInteger)index
{
    if ([self respondsToSelector:@selector(objectAtIndex:)] && [self respondsToSelector:@selector(count)]) {
        id unself = self;
        NSUInteger count = [unself count];
        if (index < count) {
            return [unself objectAtIndex:index];
        }
    }
    return nil;
}
- (void)setObject:(id)object atIndexedSubscript:(NSUInteger)index
{
    if (object == nil) {
        return;
    }
    if ([self respondsToSelector:@selector(replaceObjectAtIndex:withObject:)] &&
        [self respondsToSelector:@selector(count)]) {
        id unself = self;
        
        NSUInteger count = [unself count];
        if (index < count) {
            [unself replaceObjectAtIndex:index withObject:object];
        }
        else if ([self respondsToSelector:@selector(addObject:)]) {
            [unself addObject:object];
        }
    }
}
- (id)objectForKeyedSubscript:(id)key
{
    if ([self respondsToSelector:@selector(objectForKey:)]) {
        id unself = self;
        return [unself objectForKey:key];
    }
    return nil;
}
- (void)setObject:(id)object forKeyedSubscript:(id)key
{
    if (key == nil) {
        return;
    }
    
    if ([self respondsToSelector:@selector(setObject:forKey:)]) {
        id unself = self;
        if (object) {
            [unself setObject:object forKey:key];
        }
        else if ([unself respondsToSelector:@selector(removeObjectForKey:)]) {
            [unself removeObjectForKey:key];
        }
    }
}

- (BOOL)containsString:(NSString*)aString
{
    if ([self respondsToSelector:@selector(rangeOfString:)]) {
        if ([(id)self rangeOfString:aString].length > 0) {
            return YES;
        }
    }
    return NO;
}
- (BOOL)_accessibilityShouldSwapReceiverWithQuickSpeakPasteboard
{
    return NO;
}
@end

@implementation NSArray (Subscript)
- (id)safeInitWithObjects:(const id[])objects count:(NSUInteger)cnt
{
    for (int i = 0; i < cnt; i++) {
        if (objects[i] == nil) {
#if IS_TEST
            if (isSimulator) {
                [[MTStatusBarOverlay sharedOverlay] postFinishMessage:@"Array初始化错误..." duration:2];
            }
#endif
            return nil;
        }
    }
    
    return [self safeInitWithObjects:objects count:cnt];
}
- (id)objectAtIndexedSubscript:(NSUInteger)index
{
    if (index < self.count) {
        return [self objectAtIndex:index];
    }
    return nil;
}
@end

@implementation NSDictionary (Subscript)

- (instancetype)safeInitWithObjects:(const id[])objects forKeys:(const id<NSCopying>[])keys count:(NSUInteger)cnt
{
    for (int i = 0; i < cnt; i++) {
        if (objects[i] == nil || keys[i] == nil) {
#if IS_TEST
            if (isSimulator) {
                [[MTStatusBarOverlay sharedOverlay] postFinishMessage:@"Dictionary初始化错误..." duration:2];
            }
#endif
            return nil;
        }
    }
    return [self safeInitWithObjects:objects forKeys:keys count:cnt];
}
- (id)objectForKeyedSubscript:(id)key
{
    id value = [self objectForKey:key];
    if (value == [NSNull null] && [key isKindOfClass:[NSString class]]) {
        return nil;
    }
    return value;
}
@end
@implementation NSMutableDictionary (Subscript)
- (void)setObject:(id)object forKeyedSubscript:(id)key
{
    if (key == nil) {
        return;
    }
    
    if (object) {
        [self setObject:object forKey:key];
    }
    else {
        [self removeObjectForKey:key];
    }
}
@end
@implementation NSMapTable (Subscript)
- (id)objectForKeyedSubscript:(id)key
{
    if (key) {
        return [self objectForKey:key];
    }
    return nil;
}
- (void)setObject:(id)object forKeyedSubscript:(id)key
{
    if (key == nil)
        return;
    
    if (object) {
        [self setObject:object forKey:key];
    }
    else {
        [self removeObjectForKey:key];
    }
}
@end



@implementation NSObject(Swizzle)


+ (void)load
{
    [objc_getClass("__NSPlaceholderArray") swizzleMethod:@selector(initWithObjects:count:) withMethod:@selector(safeInitWithObjects:count:) error:nil];
    
    [objc_getClass("__NSPlaceholderDictionary") swizzleMethod:@selector(initWithObjects:forKeys:count:) withMethod:@selector(safeInitWithObjects:forKeys:count:) error:nil];
}


+ (BOOL)swizzleMethod:(SEL)origSel_ withMethod:(SEL)altSel_ error:(NSError**)error_
{
    Method origMethod = class_getInstanceMethod(self, origSel_);
    if (!origMethod) {
        return NO;
    }
    Method altMethod = class_getInstanceMethod(self, altSel_);
    if (!altMethod) {
        return NO;
    }
    
    class_addMethod(self,
                    origSel_,
                    class_getMethodImplementation(self, origSel_),
                    method_getTypeEncoding(origMethod));
    class_addMethod(self,
                    altSel_,
                    class_getMethodImplementation(self, altSel_),
                    method_getTypeEncoding(altMethod));
    
    method_exchangeImplementations(class_getInstanceMethod(self, origSel_), class_getInstanceMethod(self, altSel_));
    
    
    return YES;
}

+ (BOOL)swizzleClassMethod:(SEL)origSel_ withClassMethod:(SEL)altSel_ error:(NSError**)error_
{
    return [object_getClass((id)self) swizzleMethod:origSel_ withMethod:altSel_ error:error_];
}

@end
